home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / iijppp.lzh / src / ip.c < prev    next >
C/C++ Source or Header  |  1994-07-21  |  9KB  |  397 lines

  1. /*
  2.  *        PPP IP Protocol Interface
  3.  *
  4.  *        Written by Toshiharu OHNO (tony-o@iij.ad.jp)
  5.  *
  6.  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by the Internet Initiative Japan.  The name of the
  14.  * IIJ may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  *
  20.  *    TODO:
  21.  *        o Return ICMP message for filterd packet
  22.  *          and optionaly record it into log.
  23.  */
  24. #include "fsm.h"
  25. #include "lcpproto.h"
  26. #include "hdlc.h"
  27. #include <netinet/in_systm.h>
  28. #include <netinet/ip.h>
  29. #include <netinet/ip_icmp.h>
  30. #include <netinet/udp.h>
  31. #include <netinet/tcp.h>
  32. #include "vars.h"
  33. #include "filter.h"
  34.  
  35. extern void SendPppFlame();
  36. extern int PacketCheck();
  37. extern void LcpClose();
  38.  
  39. static struct pppTimer IdleTimer;
  40.  
  41. static void IdleTimeout()
  42. {
  43.   LogPrintf(LOG_PHASE, "Idle timer expired.\n");
  44.   LcpClose();
  45. }
  46.  
  47. /*
  48.  *  Start Idle timer. If timeout is reached, we call LcpClose() to
  49.  *  close LCP and link.
  50.  */
  51. void
  52. StartIdleTimer()
  53. {
  54.   if (!(mode & MODE_DEDICATED)) {
  55.     StopTimer(&IdleTimer);
  56.     IdleTimer.func = IdleTimeout;
  57.     IdleTimer.load = VarIdleTimeout * SECTICKS;
  58.     IdleTimer.state = TIMER_STOPPED;
  59.     StartTimer(&IdleTimer);
  60.   }
  61. }
  62.  
  63. void
  64. StopIdleTimer()
  65. {
  66.   StopTimer(&IdleTimer);
  67. }
  68.  
  69. /*
  70.  *  If any IP layer traffic is detected, refresh IdleTimer.
  71.  */
  72. static void
  73. RestartIdleTimer()
  74. {
  75.   if (!(mode & MODE_DEDICATED)) {
  76.     StopTimer(&IdleTimer);
  77.     StartTimer(&IdleTimer);
  78.     ipIdleSecs = 0;
  79.   }
  80. }
  81.  
  82. static u_short interactive_ports[8] = {
  83.   0, 513, 0, 0, 0, 21, 0, 23,
  84. };
  85.  
  86. #define    INTERACTIVE(p)    (interactive_ports[(p) & 7] == (p))
  87.  
  88. static char *TcpFlags[] = {
  89.   "FIN", "SYN", "RST", "PSH", "ACK", "URG",
  90. };
  91.  
  92. static char *Direction[] = { "INP", "OUT", "OUT" };
  93. static struct filterent *Filters[] = { ifilters, ofilters, dfilters };
  94.  
  95. static int
  96. PortMatch(op, pport, rport)
  97. int op;
  98. u_short pport, rport;
  99. {
  100.   switch (op) {
  101.   case OP_EQ:
  102.     return(pport == rport);
  103.   case OP_GT:
  104.     return(pport > rport);
  105.   case OP_LT:
  106.     return(pport < rport);
  107.   default:
  108.     return(0);
  109.   }
  110. }
  111.  
  112. /*
  113.  *  Check a packet against with defined filters
  114.  */
  115. static int
  116. FilterCheck(pip, direction)
  117. struct ip *pip;
  118. int direction;
  119. {
  120.   struct filterent *fp = Filters[direction];
  121.   int gotinfo, cproto, estab, n;
  122.   struct tcphdr *th;
  123.   struct udphdr *uh;
  124.   struct icmp *ih;
  125.   char *ptop;
  126.   u_short sport, dport;
  127.  
  128.   if (fp->action) {
  129.     cproto = gotinfo = estab = 0;
  130.     sport = dport = 0;
  131.     for (n = 0; n < MAXFILTERS; n++) {
  132.       if (fp->action) {
  133. #ifdef DEBUG
  134. logprintf("rule = %d\n", n);
  135. #endif
  136.     if ((pip->ip_src.s_addr & fp->smask.s_addr) == fp->saddr.s_addr
  137.         && (pip->ip_dst.s_addr & fp->dmask.s_addr) == fp->daddr.s_addr) {
  138.       if (fp->proto) {
  139.         if (!gotinfo) {
  140.           ptop = (char *)pip + (pip->ip_hl << 2);
  141.  
  142.           switch (pip->ip_p) {
  143.           case IPPROTO_ICMP:
  144.         cproto = P_ICMP; ih = (struct icmp *)ptop;
  145.         sport = ih->icmp_type; estab = 1;
  146.         break;
  147.           case IPPROTO_UDP:
  148.         cproto = P_UDP; uh = (struct udphdr *)ptop;
  149.         sport = ntohs(uh->uh_sport); dport = ntohs(uh->uh_dport);
  150.         estab = 1;
  151.         break;
  152.           case IPPROTO_TCP:
  153.         cproto = P_TCP; th = (struct tcphdr *)ptop;
  154.         sport = ntohs(th->th_sport); dport = ntohs(th->th_dport);
  155.         estab = (th->th_flags & TH_ACK);
  156.         break;
  157.           default:
  158.         return(A_DENY);    /* We'll block unknown type of packet */
  159.           }
  160.           gotinfo = 1;
  161. #ifdef DEBUG
  162. logprintf("dir = %d, proto = %d, srcop = %d, dstop = %d, estab = %d\n",
  163. direction, cproto, fp->opt.srcop, fp->opt.dstop, estab);
  164. if (estab == 0)
  165. logprintf("flag = %02x, sport = %d, dport = %d\n", th->th_flags, sport, dport);
  166. #endif
  167.         }
  168. #ifdef DEBUG
  169.         logprintf("check0: rule = %d, proto = %d, sport = %d, dport = %d\n",
  170.               n, cproto, sport, dport);
  171.         logprintf("check0: action = %d\n", fp->action);
  172. #endif
  173.         if (cproto == fp->proto) {
  174.           if ((fp->opt.srcop == OP_NONE ||
  175.           PortMatch(fp->opt.srcop, sport, fp->opt.srcport))
  176.            &&
  177.           (fp->opt.dstop == OP_NONE ||
  178.           PortMatch(fp->opt.dstop, dport, fp->opt.dstport))
  179.            &&
  180.           (fp->opt.estab == 0 || estab)) {
  181.         return(fp->action);
  182.           }
  183.         }
  184.       } else {
  185.         /* Address is mached. Make a decision. */
  186. #ifdef DEBUG
  187.         logprintf("check1: action = %d\n", fp->action);
  188. #endif
  189.         return(fp->action);
  190.       }
  191.     }
  192.       }
  193.       fp++;
  194.     }
  195. drop:
  196.     return(A_DENY);    /* No rule is mached. Deny this packet */
  197.   }
  198.   return(A_PERMIT);    /* No rule is given. Permit this packet */
  199. }
  200.  
  201. static void
  202. IcmpError(pip, code)
  203. struct ip *pip;
  204. int code;
  205. {
  206. #ifdef notdef
  207.   struct mbuf *bp;
  208.  
  209.   if (pip->ip_p != IPPROTO_ICMP) {
  210.     bp = mballoc(cnt, MB_IPIN);
  211.     bcopy(ptr, MBUF_CTOP(bp), cnt);
  212.     SendPppFlame(PRI_URGENT, bp);
  213.     RestartIdleTimer();
  214.     ipOutOctets += cnt;
  215.   }
  216. #endif
  217. }
  218.  
  219. /*
  220.  *  For debugging aid.
  221.  */
  222. int
  223. PacketCheck(cp, nb, direction)
  224. char *cp;
  225. int nb;
  226. int direction;
  227. {
  228.   struct ip *pip;
  229.   struct tcphdr *th;
  230.   struct udphdr *uh;
  231.   struct icmp *icmph;
  232.   char *ptop;
  233.   int mask, len, n;
  234.   int logit;
  235.   int pri = PRI_NORMAL;
  236.  
  237.   logit = (loglevel & (1 << LOG_TCPIP));
  238.  
  239.   pip = (struct ip *)cp;
  240.   
  241.   if (logit) logprintf("%s  ", Direction[direction]);
  242.  
  243.   ptop = (cp + (pip->ip_hl << 2));
  244.  
  245.   switch (pip->ip_p) {
  246.   case IPPROTO_ICMP:
  247.     if (logit) {
  248.       icmph = (struct icmp *)ptop;
  249.       logprintf("ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
  250.       logprintf("%s:%d\n", inet_ntoa(pip->ip_dst), icmph->icmp_type);
  251.     }
  252.     break;
  253.   case IPPROTO_UDP:
  254.     if (logit) {
  255.       uh = (struct udphdr *)ptop;
  256.       logprintf("UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
  257.       logprintf("%s:%d\n", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
  258.     }
  259.     break;
  260.   case IPPROTO_TCP:
  261.     th = (struct tcphdr *)ptop;
  262.     if (pip->ip_tos == IPTOS_LOWDELAY)
  263.       pri = PRI_FAST;
  264.     else if (pip->ip_off == 0) {
  265.       if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
  266.      pri = PRI_FAST;
  267.     }
  268.  
  269.     if (logit) {
  270.       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
  271.       logprintf("TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
  272.       logprintf("%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
  273.       n = 0;
  274.       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
  275.     if (th->th_flags & mask)
  276.       logprintf(" %s", TcpFlags[n]);
  277.     n++;
  278.       }
  279.       logprintf("  seq:%x  ack:%x (%d/%d)\n",
  280.     ntohl(th->th_seq), ntohl(th->th_ack), len, nb);
  281.       if ((th->th_flags & TH_SYN) && nb > 40) {
  282.         u_short *sp;
  283.  
  284.     ptop += 20;
  285.     sp = (u_short *)ptop;
  286.     if (ntohs(sp[0]) == 0x0204)
  287.       logprintf(" MSS = %d\n", ntohs(sp[1]));
  288.       }
  289.     }
  290.     break;
  291.   }
  292.   pri = FilterCheck(pip, direction);
  293.   if (pri & A_DENY) {
  294. #ifdef DEBUG
  295.     logprintf("blocked.\n");
  296. #endif
  297.     if (direction == 0) IcmpError(pip, pri);
  298.     return(-1);
  299.   } else {
  300.     return(pri);
  301.   }
  302. }
  303.  
  304. void
  305. IpInput(bp)
  306. struct mbuf *bp;        /* IN: Pointer to IP pakcet */
  307. {
  308.   u_char *cp;
  309.   struct mbuf *wp;
  310.   int nb, nw;
  311.   u_char tunbuff[MAX_MRU];
  312.  
  313.   cp = tunbuff;
  314.   nb = 0;
  315.   for (wp = bp; wp; wp = wp->next) {        /* Copy to continuois region */
  316.     bcopy(MBUF_CTOP(wp), cp, wp->cnt);
  317.     cp += wp->cnt;
  318.     nb += wp->cnt;
  319.   }
  320.  
  321.   if (PacketCheck(tunbuff, nb, 0) < 0) {
  322.     pfree(bp);
  323.     return;
  324.   }
  325.  
  326.   ipInOctets += nb;
  327.   /*
  328.    *  Pass it to tunnel device
  329.    */
  330.   nw = write(tun_out, tunbuff, nb);
  331.   if (nw != nb)
  332.     fprintf(stderr, "wrote %d, got %d\r\n");
  333.   pfree(bp);
  334.  
  335.   RestartIdleTimer();
  336. }
  337.  
  338. void
  339. IpOutput(ptr, cnt)
  340. u_char *ptr;            /* IN: Pointer to IP packet */
  341. int cnt;            /* IN: Length of packet */
  342. {
  343.   struct mbuf *bp;
  344.   int pri;
  345.  
  346.   if (IpcpFsm.state != ST_OPENED)
  347.     return;
  348.  
  349.   pri = PacketCheck(ptr, cnt, 1);
  350.   if (pri >= 0) {
  351.     bp = mballoc(cnt, MB_IPIN);
  352.     bcopy(ptr, MBUF_CTOP(bp), cnt);
  353.     SendPppFlame(pri, bp);
  354.     RestartIdleTimer();
  355.     ipOutOctets += cnt;
  356.   }
  357. }
  358.  
  359. static struct mqueue IpOutputQueues[PRI_URGENT+1];
  360.  
  361. void
  362. IpEnqueue(pri, ptr, count)
  363. int pri;
  364. char *ptr;
  365. int count;
  366. {
  367.   struct mbuf *bp;
  368.  
  369.   bp = mballoc(count, MB_IPQ);
  370.   bcopy(ptr, MBUF_CTOP(bp), count);
  371.   Enqueue(&IpOutputQueues[pri], bp);
  372. }
  373.  
  374. void
  375. IpStartOutput()
  376. {
  377.   struct mqueue *queue;
  378.   struct mbuf *bp;
  379.   int pri, cnt;
  380.  
  381.   if (IpcpFsm.state != ST_OPENED)
  382.     return;
  383.   pri = PRI_URGENT;
  384.   for (queue = &IpOutputQueues[PRI_URGENT]; queue >= IpOutputQueues; queue--) {
  385.     if (queue->top) {
  386.       bp = Dequeue(queue);
  387.       if (bp) {
  388.     cnt = plength(bp);
  389.     SendPppFlame(pri, bp);
  390.     RestartIdleTimer();
  391.     ipOutOctets += cnt;
  392.        }
  393.     }
  394.     pri--;
  395.   }
  396. }
  397.